/*
 ============================================================================
 Name        : measure_time.c
 Author      : CWHUANG
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/times.h>

int clock_time_diff(struct timespec start, struct timespec end, struct timespec *diff);



int main(void) {

	puts("Measuring time used by process both in user- and system-mode"); /* prints Measuring time used by process both in user- and system-mode */
	printf("CLOCKS_PER_SEC is %ld\n", CLOCKS_PER_SEC);

	clock_t start, end;

	struct tms start_user_sys_time;
	struct tms end_user_sys_time;

	start = times(&start_user_sys_time);
	start = clock();
	struct timespec a,b;
	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &a);
	struct timeval timea, timeb;
	gettimeofday(&timea, NULL);
//  Work to be measured start here
	int i;
	double j;
	for(i=0; i<5000000; i++){
		j= (double) i/3;
	}
	sleep(2);  // surely did not count
//  Work to be measured ends here


	end = times(&end_user_sys_time);
	end = clock();	// resolution is 10 ms, too coarse!!
	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b); //high-resolution timer provided by the CPU for each process.
	gettimeofday(&timeb, NULL);  // using gettimeofday, we obtain calendar time. so sleeping time will be included!!

	printf("start: %ld; end: %ld\n",  start,  end);
	printf("start user time: %ld; end user time: %ld\n", start_user_sys_time.tms_utime, end_user_sys_time.tms_utime);
	printf("start sys  time: %ld; end sys  time: %ld\n", start_user_sys_time.tms_stime, end_user_sys_time.tms_stime);

	printf("Real Time: %ld, User Time %ld, System Time %ld\n",
	        (end - start),
	        (end_user_sys_time.tms_utime - start_user_sys_time.tms_utime),
	        (end_user_sys_time.tms_stime - start_user_sys_time.tms_stime));
	printf("gettimeofday: %ld sec, %ld micro-second\n", timeb.tv_sec-timea.tv_sec, timeb.tv_usec-timea.tv_usec);
//	printf("junk %f\n", j);

	struct timespec res;
	clock_getres(CLOCK_PROCESS_CPUTIME_ID, &res);
	printf("clock_id: %d with resolution %ld sec %ld nanosecond\n", CLOCK_PROCESS_CPUTIME_ID,res.tv_sec, res.tv_nsec);

	printf("Using clock_gettime: %ld sec, %ld nanosecond\n", b.tv_sec - a.tv_sec, b.tv_nsec - a.tv_nsec);
	struct timespec diff;
	clock_time_diff(a, b, &diff);
	printf("Using clock_gettime: %ld sec, %ld nanosecond\n", diff.tv_sec, diff.tv_nsec);

	return EXIT_SUCCESS;
}

int clock_time_diff(struct timespec start, struct timespec end, struct timespec *diff)
{
	if ((end.tv_nsec-start.tv_nsec)<0) {
		diff->tv_sec = end.tv_sec-start.tv_sec-1;
		diff->tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
	} else {
		diff->tv_sec = end.tv_sec-start.tv_sec;
		diff->tv_nsec = end.tv_nsec-start.tv_nsec;
	}
	return 0;
}
